package com.tanzc.mp3player;

import com.tanzc.mp3player.filter.FilenameSuffixFilter;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.advanced.AdvancedPlayer;

import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.nio.file.FileSystemException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p> description: description </p>
 *
 * @author tanzc
 * @date 15:54 2021/5/27
 **/
public class Mp3PlayerV2 {
    private AdvancedPlayer player;

    private List<String> mp3List;

    /*
        音乐播放控制参数，初始化为0
        0-正常播放，
        1-下一曲，
        2-停止播放
     */
    private static Integer controlKey;

    private static boolean playEnd;

    Thread playerThread;

    final private File mp3Dir;

    final private FilenameFilter filter;


    public static void main(String[] args) throws FileSystemException, FileNotFoundException {
        Mp3PlayerV2 mp3Player = new Mp3PlayerV2(new File("G:\\music\\mp3"), "mp3");
        // 正常开始播放
        new Thread(() -> {
            try {
                mp3Player.playRotate();
            } catch (FileSystemException | FileNotFoundException | JavaLayerException e) {
                e.printStackTrace();
            }
        }).start();
        // 每10秒模拟一次下一曲，共2次
        for (int i = 0; i < 2; i++) {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mp3Player.setControlKey(1);
        }
        // 模拟停止信号
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        mp3Player.setControlKey(2);
    }


    public Mp3PlayerV2(File mp3Dir, String musicType) throws FileSystemException, FileNotFoundException {
        this.mp3Dir = mp3Dir;
        this.filter = new FilenameSuffixFilter(musicType);
        controlKey = 0;
        playEnd = false;
        setMp3List(mp3Dir);
    }

    public void setControlKey(Integer key) {
        controlKey = key;
    }

    private int getProcessId() {
        RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
        return Integer.parseInt(runtimeMxBean.getName().split("@")[0]);
    }

    public void initPlayer(File mp3) throws FileNotFoundException, JavaLayerException {
        FileInputStream fileInputStream = new FileInputStream(mp3);
        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
        player = new AdvancedPlayer(bufferedInputStream);
    }

    /**
     * <p> Description: 更新mp3音乐列表</p>
     *
     * @param musicDir musicDir
     * @return java.util.List<java.lang.String>
     **/
    public List<String> setMp3List(File musicDir) throws FileSystemException, FileNotFoundException {
        if (!musicDir.isDirectory()) {
            throw new FileSystemException("invalid directory: " + musicDir);
        }
        String[] mp3Array = musicDir.list(filter);
        if (mp3Array == null || mp3Array.length == 0) {
            throw new FileNotFoundException("no mp3 file in directory: " + musicDir);
        }
        mp3List = new ArrayList<>(Arrays.asList(mp3Array));
        return mp3List;
    }

    public void play(File mp3) throws FileNotFoundException, JavaLayerException {
        initPlayer(mp3);
        new Thread(() -> {
            try {
                player.play();
                playEnd = true;
            } catch (JavaLayerException e) {
                e.printStackTrace();
            }
        }).start();
//        System.out.println("新开线程执行AdvancedPlayer.play()，主线程不阻塞");
    }

    private void stop() {
//        player.stop();
        player.close();
    }

    public void playRotate() throws FileSystemException, FileNotFoundException, JavaLayerException {
        System.out.println("playRotate-->");
        String currentMp3 = null;
        int size = mp3List.size(), index, randomSize = size - size / 3;

        while (controlKey != 2) {
            // 随机选中下一首播放歌曲
            currentMp3 = mp3List.get((int) Math.floor(Math.random() * randomSize));

            // 放进线程播放
            System.out.println("play-->" + currentMp3);
//            playerThread = new PlayerThread(this, new File(mp3Dir, currentMp3));
//            playerThread.start();
            play(new File(mp3Dir, currentMp3));
            playEnd = false;
            // 线程未结束，等待控制器控制信息
//            while (!"TERMINATED".equals(playerThread.getState().toString())) {
            while (playEnd != true) {
                try {
                    // 不那么频繁读取控制信息
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 读取到下一曲或停止播放信号
                if (controlKey != 0) {
//                    playerThread.interrupt();
                    stop();
                    // 如果控制信号为下一曲，则重置controlKey为正常播放状态
                    if (controlKey == 1) {
                        setControlKey(0);
                    }
                    break;
                }
            }
            // 停止信息，则直接退出循环播放
            if (controlKey == 2) {
                break;
            }

            // 播放完一首歌，检查音乐数量
            if (mp3Dir.list(filter).length != mp3List.size()) {
                setMp3List(mp3Dir);
                size = mp3List.size();
                randomSize = size - size / 3;
            }
            // 刚播放的放到队尾
            mp3List.remove(currentMp3);
            mp3List.add(currentMp3);
        }
    }


    static class PlayerThread extends Thread {
        private Mp3PlayerV2 mp3PlayerV2;
        private File mp3;

        PlayerThread(Mp3PlayerV2 mp3PlayerV2, File mp3) {
            this.mp3PlayerV2 = mp3PlayerV2;
            this.mp3 = mp3;
        }

        @Override
        public void run() {
            try {
                mp3PlayerV2.play(mp3);
            } catch (FileNotFoundException | JavaLayerException e) {
                e.printStackTrace();
            }
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("playerThread收到中断信号，停止播放");
                    mp3PlayerV2.stop();
                    break;
                }
            }
        }
    }
}
